package com.example.server.service.impl;

import com.example.server.service.ECityService;
import com.example.server.api.dto.ElasticCityDto;
import com.example.server.entity.ElasticCity;
import com.example.server.repository.ElasticCityRepository;
import com.example.server.utils.AdvancedBeanUtils;
import com.example.server.utils.ElasticsearchHelper;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.BeanUtils;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.mapping.IndexCoordinates;
import org.springframework.data.elasticsearch.core.query.IndexBoost;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.stereotype.Service;


import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class CityServiceImpl implements ECityService {

    @Resource
    private ElasticCityRepository elasticCityRepository;

    @Resource
    private ElasticsearchRestTemplate elasticsearchRestTemplate;

    @Override
    public ElasticCityDto saveCity(ElasticCityDto cityDto) {

//        return cityDto;
//        return null;
        RestHighLevelClient conn = ElasticsearchHelper.getConnection();
        // 使用常规方式向elasticsearch中添加数据
        IndexRequest request = new IndexRequest("citys", "_doc", cityDto.getId().toString());
        Map<String, Object> jsonMap = new HashMap<>();
        jsonMap.put("id", 4);
        jsonMap.put("name", "成都");
        request.source(jsonMap);
        try {
            IndexResponse indexResponse = conn.index(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }
        ElasticCity city = new ElasticCity((Integer) jsonMap.get("id"), (String) jsonMap.get("name"));
        ElasticCityDto newCityDto = new ElasticCityDto();
        BeanUtils.copyProperties(city, newCityDto);
        return newCityDto;
    }

    @Override
    public List<ElasticCityDto> listCity() {
        Iterable<ElasticCity> cities = this.elasticCityRepository.findAll();
        List<ElasticCityDto> cityList = new ArrayList<>();
        for (ElasticCity elasticCity : cities) {
            ElasticCityDto elasticCityDto = AdvancedBeanUtils.copyProperties(elasticCity, ElasticCityDto.class);
            cityList.add(elasticCityDto);
        }
        return cityList;
    }

    @Override
    public boolean addCity(ElasticCityDto cityDto) {
        ElasticCity city = AdvancedBeanUtils.copyProperties(cityDto, ElasticCity.class);
        // 保存结束返回传入的city对象
        this.elasticCityRepository.save(city);
        return true;
    }

    @Override
    public List<ElasticCityDto> listTop(int num) {
        // 查询 排序 分页
        List<IndexBoost> indexBoostList = new ArrayList<>();
        indexBoostList.add(new IndexBoost("citys", 1f));
        NativeSearchQuery query = new NativeSearchQueryBuilder()
                .withIndicesBoost(indexBoostList)
                .withQuery(QueryBuilders.matchAllQuery())
                .withSort(new FieldSortBuilder("id").order(SortOrder.ASC))
                .withPageable(PageRequest.of(0, num))
                .build();
        IndexCoordinates indexCoordinates = IndexCoordinates.of("citys");
        // elasticsearchRestTemplate所在的包Spring Data Elasticsearch最新版删除了queryForList以及queryForPage
        // 此处使用最新的发行版4.0.9.RELEASE
        AggregatedPage<ElasticCity> cities = this.elasticsearchRestTemplate.queryForPage(query, ElasticCity.class, indexCoordinates);
        List<ElasticCityDto> cityDto = new ArrayList<>();
        cities.forEach(item -> cityDto.add(AdvancedBeanUtils.copyProperties(item, ElasticCityDto.class)));
        return cityDto;
    }
}
